package com.business.lgh.nacosclient;

import com.business.lgh.nacos.api.common.PropertyKeyConst;
import com.business.lgh.nacos.api.naming.common.CommonParams;
import com.business.lgh.nacos.api.naming.pojo.Instance;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author lgh
 * @version V1.0
 * @Package com.business.lgh.nacosclient
 * @date 2020/6/25 2:43 下午
 */
@Slf4j
public class NacosNamingService implements NamingService {

    public static final String HTTP = "http://";
    public static final String UTF_8 = "UTF-8";
    Properties properties;
    OkHttpClient client = new OkHttpClient();

    private List<String> serverList;

    public NacosNamingService(Properties properties) {
        this.properties = properties;
        initServer();
    }

    private void initServer(){
        String serverList=properties.getProperty(PropertyKeyConst.SERVER_ADDR);
        if (StringUtils.isNotEmpty(serverList)) {
            this.serverList = Arrays.asList(serverList.split(","));
        }
    }

    @Override
    public void registerInstance(String s, Instance instance) {
        final Map<String,String> params=new HashMap<>();
        params.put(CommonParams.NAMESPACE_ID,"default");
        params.put(CommonParams.SERVICE_NAME,instance.getServiceName());
        params.put(CommonParams.GROUP_NAME,"defaultGroup");
        params.put(CommonParams.CLUSTER_NAME,instance.getClusterName());
        params.put("ip",instance.getIp());
        params.put("port",String.valueOf(instance.getPort()));
        params.put("ephemeral","true");
        ///nacos/v1/ns/instance
        String path="/nacos/v1/ns/instance";
        String result = null;
        try {
            result = reqRibbonApi(serverList, path, params, HttpMethod.POST);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        log.info(result);
    }
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");


    private String reqRibbonApi(List<String> serverList, String path, Map<String, String> params, HttpMethod post) throws UnsupportedEncodingException {
        if (serverList==null||serverList.size()==0){
            log.error("服务信息为空");
            return "服务信息为空";
        }

        Random random=new Random(serverList.size()+10);
        int index = random.nextInt(serverList.size());
        String encodedContent = encodingParams(params, UTF_8);

        for (int i = 0; i < serverList.size(); i++) {
            String server=serverList.get(index);
            try {
                //构建URL
                String url=HTTP +server+path;
                url += (StringUtils.isEmpty(encodedContent)) ? "" : ("?" + encodedContent);

                //构建请求参数
                Request request = new Request.Builder()
                        .url(url)
                        .post(new FormBody.Builder().build())
                        .build();

                //发送请求
                Response response = client.newCall(request).execute();
                return response.body().string();
            }catch (Exception ex){
                ex.printStackTrace();
            }
            //若请求异常则轮询下一个注册中心进行注册
            index=(index+1)%serverList.size();
        }
        return "";
    }

    private static String encodingParams(Map<String, String> params, String encoding)
            throws UnsupportedEncodingException {
        if (null == params || params.isEmpty()) {
            return "";
        }

        params.put("encoding", encoding);
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (StringUtils.isEmpty(entry.getValue())) {
                continue;
            }

            sb.append(entry.getKey()).append("=");
            sb.append(URLEncoder.encode(entry.getValue(), encoding));
            sb.append("&");
        }

        if (sb.length() > 0) {
            sb = sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

}
